package com.lzj.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lzj.admin.controller.HelloController;
import com.lzj.admin.mapper.UserRoleMapper;
import com.lzj.admin.pojo.User;
import com.lzj.admin.mapper.UserMapper;
import com.lzj.admin.pojo.UserRole;
import com.lzj.admin.query.UserQuery;
import com.lzj.admin.service.IRoleService;
import com.lzj.admin.service.IUserRoleService;
import com.lzj.admin.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lzj.admin.utils.AssertUtil;
import com.lzj.admin.utils.PageResultUtil;
import com.lzj.admin.utils.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author luoyoumou
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Resource
    private PasswordEncoder passwordEncoder;

    @Resource
    private IUserRoleService userRoleService;

    @Resource
    UserRoleMapper userRoleMapper;

    @Resource
    private IRoleService roleService;

    @Override
    public User findUserByUserName(String userName) {
        return this.baseMapper.selectOne(new QueryWrapper<User>().eq("is_del",0).eq("name",userName));
    }

    public User findAdminUser() {
        return this.baseMapper.selectOne(new QueryWrapper<User>().eq("name","admin"));
    }

    /**
     * 用户信息 - 更新
     * 用户名
     *    非空
     *    唯一
     * @param user
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void updateUserInfo(User user) {
        AssertUtil.isTrue(StringUtil.isEmpty(user.getUsername()),"用户名不能为空!");
        User temp = this.findUserByUserName(user.getUsername());
        AssertUtil.isTrue(null !=temp && !(temp.getId().equals(user.getId())),"用户名已存在!");
        AssertUtil.isTrue(!(this.updateById(user)),"用户信息记录更新失败!");
    }

    /**
     * 用户密码 - 更新
     *  用户名非空 必须存在
     *  原始密码 新密码 确认密码 均不能为空
     *  原始密码必须正确
     *  新密码 与 确认密码必须一致  并且不能与原始密码相同
     * @param userName
     * @param oldPassword
     * @param newPassword
     * @param confirmPassword
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void updateUserPassword(String userName, String oldPassword, String newPassword, String confirmPassword) {
        User user=null;
        user = this.findUserByUserName(userName);
        AssertUtil.isTrue(null==user,"用户不存在或未登录!");
        AssertUtil.isTrue(StringUtil.isEmpty(oldPassword),"请输入原始密码!");
        AssertUtil.isTrue(StringUtil.isEmpty(newPassword),"请输入新密码!");
        AssertUtil.isTrue(StringUtil.isEmpty(confirmPassword),"请输入确认密码!");
        AssertUtil.isTrue(!(passwordEncoder.matches(oldPassword,user.getPassword())),"原始密码输入错误!");
        AssertUtil.isTrue(!(newPassword.equals(confirmPassword)),"新密码输入不一致!");
        AssertUtil.isTrue(newPassword.equals(oldPassword),"新密码与原始密码不能一致!");
        user.setPassword(passwordEncoder.encode(newPassword));
        AssertUtil.isTrue(!(this.updateById(user)),"用户密码更新失败!");

    }

    @Override
    public Map<String, Object> userList(UserQuery userQuery) {
        IPage<User> page = new Page<User>(userQuery.getPage(),userQuery.getLimit());
        page = this.baseMapper.queryUserByParams(page,userQuery);
        return PageResultUtil.getResult(page.getTotal(),page.getRecords());
    }

    /**
     * 用户信息 - 添加
     * 用户名
     *  非空
     *  不能重复
     * 用户密码默认： 123456
     * 用户默认有效
     * @param user
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void saveUser(User user) {
        AssertUtil.isTrue(StringUtils.isBlank(user.getUsername()),"用户名不能为空！");
        AssertUtil.isTrue(null != this.findUserByUserName(user.getUsername()),"用户名已存在！");
        user.setPassword(passwordEncoder.encode("123456"));
        user.setIsDel(0);
        AssertUtil.isTrue(!(this.save(user)),"用户信息添加失败！");
        // 重新查询用户记录 // 后续可以优化，省掉这步查询
        User tempUser = this.findUserByUserName(user.getUsername());
        /**
         * 给用户分配角色
         */
        relationUserRole(tempUser.getId(),user.getRoleIds());
    }

    /**
     * 用户 授权角色信息
     * 核心表 t_user_role
     *  添加时
     *      如果角色记录存在 执行批量添加即可
     *  更新时
     *      如果用户存在原始的角色记录
     *          如果存在 直接删除原来的用户角色记录  重新添加新的用户角色记录
     *          如果不存在 直接执行添加即可
     *
     * 实现思路
     *  首先查询用户原始分配角色
     *      如果存在原始用户角色记录 直接删除原来用户角色记录即可（根据用户id) 然后重新添加新的用户角色记录
     *      如果不存在 直接执行批量添加即可
     * @param userId
     * @param roleIds
     */
    private void relationUserRole(Integer userId, String roleIds) {
        QueryWrapper<UserRole> queryWrapper = new QueryWrapper<UserRole>().eq("user_id",userId).last("limit 1");
        List<UserRole> tmpUserRoles = userRoleMapper.selectList(queryWrapper);
        if(CollectionUtils.isNotEmpty(tmpUserRoles)){
            AssertUtil.isTrue(!(userRoleService.remove(new QueryWrapper<UserRole>().eq("user_id",userId))),"用户角色分配失败！");
        }
        if(StringUtils.isNotBlank(roleIds)){
            /**
             * 1,2,3,4
             */
            List<UserRole> userRoles = new ArrayList<UserRole>();
            for (String s : roleIds.split(",")) {
               UserRole userRole = new UserRole();
               userRole.setUserId(userId);
               userRole.setRoleId(Integer.parseInt(s));
               userRoles.add(userRole);
            }
            AssertUtil.isTrue(!(userRoleService.saveBatch(userRoles)),"用户角色分配失败！");
        }
    }

    /**
     * 用户信息 - 更新
     * 用户名
     *  非空 不能重复
     *  admin 用户名 不能被修改
     * @param user
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void updateUser(User user) {
        AssertUtil.isTrue(StringUtils.isBlank(user.getName()),"用户名不能为空！");
        User tempUser = this.findUserByUserName(user.getName());
        AssertUtil.isTrue(null != tempUser && !(tempUser.getId().equals(user.getId())),"用户名已存在！");
        User adminUser = this.findAdminUser();
        AssertUtil.isTrue( user.getId() == adminUser.getId() && !(user.getName().equals(adminUser.getName())),"admin用户名不能被修改！");
        Integer uid = user.getId();
        relationUserRole(user.getId(), user.getRoleIds());
        AssertUtil.isTrue(!(this.updateById(user)),"用户信息更新失败！");
    }

    /**
     * 用户信息 - 删除
     *   admin 用户不能被删除
     *   当前登录用户不能被删除，即自己不能删除自己
     * @param ids
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void deleteUser(Integer[] ids) {
        AssertUtil.isTrue(null == ids || ids.length == 0, "请选择待删除的用户id！");
        int count = userRoleService.count(new QueryWrapper<UserRole>().in("user_id", Arrays.asList(ids)));
        if(count>0){
            AssertUtil.isTrue(!(userRoleService.remove(new QueryWrapper<UserRole>().in("user_id", Arrays.asList(ids)))),"用户记录删除失败！");
        }
        List<User> users = new ArrayList<User>();
        for(Integer id : ids) {
            User tempUser = this.getById(id);
            AssertUtil.isTrue(tempUser.getName().equals("admin"),"admin用户不能被删除！");
            AssertUtil.isTrue(tempUser.getName().equals(HelloController.hello()),"当前登录用户不能被删除！");
            tempUser.setIsDel(1);
            users.add(tempUser);
        }
        AssertUtil.isTrue(!(this.updateBatchById(users)),"用户信息删除失败！");
    }

}
